using System;

namespace winsw
{
	public class PeriodicRollingCalendar
	{
		public enum PeriodicityType
		{
			ERRONEOUS,
			TOP_OF_MILLISECOND,
			TOP_OF_SECOND,
			TOP_OF_MINUTE,
			TOP_OF_HOUR,
			TOP_OF_DAY
		}

		private PeriodicityType _periodicityType;

		private string _format;

		private long _period;

		private DateTime _currentRoll;

		private DateTime _nextRoll;

		private static PeriodicityType[] VALID_ORDERED_LIST = new PeriodicityType[5]
		{
			PeriodicityType.TOP_OF_MILLISECOND,
			PeriodicityType.TOP_OF_SECOND,
			PeriodicityType.TOP_OF_MINUTE,
			PeriodicityType.TOP_OF_HOUR,
			PeriodicityType.TOP_OF_DAY
		};

		public PeriodicityType periodicityType
		{
			set
			{
				_periodicityType = value;
			}
		}

		public bool shouldRoll
		{
			get
			{
				DateTime now = DateTime.Now;
				if (now > _nextRoll)
				{
					_currentRoll = now;
					_nextRoll = nextTriggeringTime(now, _period);
					return true;
				}
				return false;
			}
		}

		public string format => _currentRoll.ToString(_format);

		public PeriodicRollingCalendar(string format, long period)
		{
			_format = format;
			_period = period;
			_currentRoll = DateTime.Now;
		}

		public void init()
		{
			_periodicityType = determinePeriodicityType();
			_nextRoll = nextTriggeringTime(_currentRoll, _period);
		}

		private PeriodicityType determinePeriodicityType()
		{
			PeriodicRollingCalendar periodicRollingCalendar = new PeriodicRollingCalendar(_format, _period);
			DateTime input = new DateTime(1970, 1, 1);
			PeriodicityType[] vALID_ORDERED_LIST = VALID_ORDERED_LIST;
			foreach (PeriodicityType periodicityType in vALID_ORDERED_LIST)
			{
				string text = input.ToString(_format);
				periodicRollingCalendar.periodicityType = periodicityType;
				string text2 = periodicRollingCalendar.nextTriggeringTime(input, 1L).ToString(_format);
				if (text != null && text2 != null && !text.Equals(text2))
				{
					return periodicityType;
				}
			}
			return PeriodicityType.ERRONEOUS;
		}

		private DateTime nextTriggeringTime(DateTime input, long increment)
		{
			switch (_periodicityType)
			{
			case PeriodicityType.TOP_OF_MILLISECOND:
				return new DateTime(input.Year, input.Month, input.Day, input.Hour, input.Minute, input.Second, input.Millisecond).AddMilliseconds(increment);
			case PeriodicityType.TOP_OF_SECOND:
				return new DateTime(input.Year, input.Month, input.Day, input.Hour, input.Minute, input.Second).AddSeconds(increment);
			case PeriodicityType.TOP_OF_MINUTE:
				return new DateTime(input.Year, input.Month, input.Day, input.Hour, input.Minute, 0).AddMinutes(increment);
			case PeriodicityType.TOP_OF_HOUR:
				return new DateTime(input.Year, input.Month, input.Day, input.Hour, 0, 0).AddHours(increment);
			case PeriodicityType.TOP_OF_DAY:
				return new DateTime(input.Year, input.Month, input.Day).AddDays(increment);
			default:
				throw new Exception("invalid periodicity type: " + _periodicityType);
			}
		}
	}
}
